#ifndef _BC_MULTIBARCODES_H_
#define _BC_MULTIBARCODES_H_

//External classes
class CBC_Reader;
class CBC_Writer;

//Classes defined in this header
class CBC_MultiBarCodes;

//
void BC_Library_Init();

//
void BC_Library_Destory();

/*Error Correct Level For QR code*/
#define BCFORMAT_ECLEVEL_L 0
#define BCFORMAT_ECLEVEL_M 1
#define BCFORMAT_ECLEVEL_Q 2
#define BCFORMAT_ECLEVEL_H 3

/**/
enum BCFORMAT
{
	BCFORMAT_UNSPECIFY = -1,
	BCFORMAT_CODABAR,
	BCFORMAT_CODE_39,
	BCFORMAT_CODE_93,
	BCFORMAT_CODE_128,
	BCFORMAT_CODE_128B,
	BCFORMAT_CODE_128C,
	BCFORMAT_EAN_8,
	BCFORMAT_UPC_A,
	BCFORMAT_EAN_13,
	BCFORMAT_ITF,
	BCFORMAT_PDF_417,
	BCFORMAT_RSS_14,
	BCFORMAT_RSS_EXPANDED,
	BCFORMAT_UPC_E,
	BCFORMAT_DATAMATRIX,
	BCFORMAT_QR_CODE
};

#define	BCExceptionNO											           0
#define	BCExceptionFormatException								           8
#define BCExceptionFailToCreateBitmap									  80

//*****************************************************************************
//* CBC_MultiBarCodes
//*****************************************************************************
class CBC_MultiBarCodes : public CFX_Object
{
public:
	static CBC_MultiBarCodes* Create(FX_BOOL bShowCharacters = TRUE, IFX_Allocator *pAllocator = NULL);
	virtual ~CBC_MultiBarCodes();

	/**
	* Use this method to set the color space of a barcode bitmap.
	*
	* @param[in] format	 the color space of bitmap. FXDIB_Argb or FXDIB_Cmyk Only.
	*/
	void SetColorSpace(FXDIB_Format format);

	/**
	* Use this method to set the font of the string showed at bottom in a barcode bitmap.
	* Only available for 1D Barcode. 
	*
	* @param[in] fontName	the name of font.
	*/
	void SetCharacterFont(const CFX_ByteString &fontName);

	/**
	* Use this method to decide to show the string or not  in a barcode bitmap.
	* Only available for 1D Barcode.
	*
	* @param[in] bShow		true means show and false does not
	*/
	void ShowCharacters(FX_BOOL bShow = TRUE);

	/**
	* Use this method to set the color which is default black in a barcode bitmap.
	*
	* @param[in] foreground		The foreground color.
	*/
	void SetForeground(FX_DWORD foreground);

	/**
	* Use this method to set the color which is default white in a barcode bitmap.
	*
	* @param[in] background		The background color.
	*/
	void SetBackground(FX_DWORD background);

	/**
	* Use this method to decode a bitmap containing a barcode image.
	* if the bitmap doesn't contain a barcode or others, this method will
	* throw an exception to inform of fail decoding.
	*
	* @param[in] pBitmap			a bitmap containing a barcode image.
	* @param[in] format				specify the codeformat to decode this bitmap.
	*								Note: UNSPECIFY means auto-decoding without specifying the barcode format
	* @param[in] hints				reserved.
	*/
	CFX_WideString Decode(CFX_DIBitmap *pBitmap, BCFORMAT &format, FX_INT32 &e, FX_INT32 hints = 0);

	/**
	* Use this method to decode a file containing a barcode image.
	* if the file doesn't contain a barcode image or others, this method will
	* throw an exception to inform of fail decoding.
	*
	* @param[in] filename			a file containing a barcode image.
	* @param[in] format				specify the codeformat to decode this file.
	*								Note: UNSPECIFY means auto-decoding without specifying the barcode format
	* @param[in] hints				reserved.
	*/
	CFX_WideString Decode(const CFX_WideString &filename, BCFORMAT &format, FX_INT32 &e, FX_INT32 hints = 0);

	/**
	* Use this method to encode a string to a 2D-byte matrix with specifying a barcode format.
	* if failing to encode the string, this method will throw an exception to inform of fail encoding.
	*
	* @param[in] contents			a string needed to be encoded to a a 2D-byte matrix.	
	* @param[out] invalidContents	output the invalid encoded string.
	* @param[in] format				specify a codeformat to encode this string.
	* @param[out] outWidth			output the 2D matrix's width.
	* @param[out] outHeight			output the 2D matrix's height. if format is 1D barcode, outHeight is always 1.
	* @param[out] ecLevel			only available for QR format.
	* @return Value					output the 2D matrix's data. need to delete manually.
	*/
	FX_BYTE* Encode(const CFX_WideString &contents, CFX_WideString &invalidContents, BCFORMAT format, FX_INT32 &outWidth, FX_INT32 &outHeight, FX_INT32 &e, FX_INT32 ecLevel = 0);
	
	/**
	* Use this method to encode a string to a bitmap with specifying a barcode format.
	* if failing to encode the string, this method will throw an exception to inform of fail encoding.
	*
	* @param[out] pOutBitmap		output the bitmap containing a specfied-format barcode image. need to delete manually.
	* @param[in] contents			a string needed to be encoded to a bitmap.
	* @param[in] format				specify a codeformat to encode this string.
	* @param[in] moduleHSize		specify the module width of one unit.
	* @param[in] moduleVSize		specify the module height of one unit.
	* @param[in] ecLevel			only available for QR format.
	*/
	void Encode(CFX_DIBitmap *&pOutBitmap, const CFX_WideString &contents, BCFORMAT format, FX_INT32 moduleHSize, FX_INT32 moduleVSize, FX_INT32 &e, FX_INT32 ecLevel = 0);
	
	/**
	* Use this method to release the resource used by this library.
	* can ONLY call ONCE, more than once call definitely causes a crash.
	*
	*/
	static void ReleaseAll();

protected:
	CBC_MultiBarCodes(FX_BOOL bShowCharacters = TRUE, IFX_Allocator *pAllocator = NULL);
	void Init();

private:
	CFX_ArrayTemplate<CBC_Reader*> m_barcodeReaders;
	CFX_ArrayTemplate<CBC_Writer*> m_barcodeWriters;

	FX_INT32 m_bShowCharacters;

	CFX_ByteString m_fontName;

	FX_DWORD m_foregroundColor;
	FX_DWORD m_backgroundColor;

	FXDIB_Format m_colorSpace;

	CFX_Font *cFont;

	IFX_Allocator *m_pAllocator;
private:
	CFX_DIBitmap* CreateDIBitmap(FX_INT32 width, FX_INT32 height);

	//void CheckEANString(const CFX_ByteString &contents, BCFORMAT format, FX_INT32 &e);
	void CheckITFString(const CFX_WideString &contents, FX_INT32 &e);

	CFX_WideString CheckCode39Contents(FX_WSTR contents, FX_BOOL extendedMode = FALSE);
	CFX_WideString CheckCode39ExtendedContents(FX_WSTR contents);
	CFX_WideString CheckCode128Contents(FX_WSTR contents, BCFORMAT codeFormat);
	CFX_WideString CheckCodeBarContents(FX_WSTR contents);
	CFX_WideString CheckEAN8String(FX_WSTR contents);
	CFX_WideString CheckEAN13String(FX_WSTR contents);
	CFX_WideString CheckUPCAString(FX_WSTR contents);

	void Render1DResult(CFX_DIBitmap *&pOutBitmap, const CFX_WideString &contents, const BCFORMAT &format, FX_BYTE* code, FX_INT32 codeLength, FX_INT32 moduleHSize, FX_INT32 moduleVSize, FX_INT32 &e);
	void Render2DResult(CFX_DIBitmap *&pOutBitmap, const BCFORMAT &format, FX_BYTE *code, FX_INT32 codeWidth, FX_INT32 codeHeight, FX_INT32 moduleHSize, FX_INT32 moduleVSize, FX_INT32 &e);
};

#endif // _BC_MULTIBARCODES_H_
